package server

import (
	"fmt"
	"os"
	"strings"
	"syscall"
	"time"

	"github.com/shirou/gopsutil/v3/process"
	"github.com/zh-five/xdaemon"
	"gopkg.openfuyao.cn/bkecommon/ntp"

	"gopkg.openfuyao.cn/bkeadm/pkg/global"
	"gopkg.openfuyao.cn/bkeadm/utils"
	"gopkg.openfuyao.cn/bkeadm/utils/log"
)

var logFile = "/tmp/ntpserver.log"

func DaemonNTPServer() {
	de := xdaemon.NewDaemon(logFile)
	de.MaxCount = 2
	de.Run()
	ntp.Serve(utils.DefaultNTPServerPort)
}

func TryConnectNTPServer(ntpServer string) bool {
	for i := 0; i < 5; i++ {
		time.Sleep(1 * time.Second)
		if err := ntp.Date(ntpServer); err == nil {
			log.BKEFormat(log.INFO, fmt.Sprintf("Connection the ntp server %s succeeds.", ntpServer))
			return true
		}
	}
	log.BKEFormat(log.WARN, fmt.Sprintf("Connection the ntp server %s refused.", ntpServer))
	return false
}

func RemoveNTPServer() error {
	var err error
	if utils.Exists("/etc/systemd/system/ntpserver.service") {
		// Remove the ntp server
		err = global.Command.ExecuteCommand("sh", "-c", "sudo systemctl disable ntpserver.service")
		if err != nil {
			log.BKEFormat(log.WARN, fmt.Sprintf("Failed to disable ntp server: %v", err))
		}
		err = global.Command.ExecuteCommand("sh", "-c", "sudo systemctl stop ntpserver.service")
		if err != nil {
			log.BKEFormat(log.WARN, fmt.Sprintf("Failed to stop ntp server: %v", err))
		}
		err = os.Remove("/etc/systemd/system/ntpserver.service")
		if err != nil {
			log.BKEFormat(log.WARN, fmt.Sprintf("Failed to remove systemd service file: %v", err))
		}
		err = global.Command.ExecuteCommand("sh", "-c", "sudo systemctl daemon-reload")
		if err != nil {
			log.BKEFormat(log.WARN, fmt.Sprintf("Failed to daemon-reload ntp server: %v", err))
		}
	}

	pids, err := process.Pids()
	if err != nil {
		return err
	}
	for _, pid := range pids {
		pn, err := process.NewProcess(pid)
		if err != nil {
			continue
		}
		cmd, err := pn.Cmdline()
		if err != nil {
			continue
		}
		if strings.Contains(cmd, "bke start ntpserver") {
			err = syscall.Kill(int(pid), syscall.SIGKILL)
			if err != nil {
				return err
			}
		}
	}
	// Remove the ntp server
	_ = os.Remove(logFile)

	log.BKEFormat(log.INFO, "Remove the ntp server")
	return nil
}

func SystemdNTPServer() {
	var err error
	bin := os.Getenv("bke")
	if len(bin) == 0 {
		bin, err = utils.ExecPath()
		if err != nil {
			log.BKEFormat(log.ERROR, fmt.Sprintf("Failed to obtain the execution path %s", err.Error()))
			return
		}
	}

	service := `
[Unit]
Description=Network Time Protocol

[Service]
ExecStart=%s start ntpserver --foreground
Restart=on-failure
RestartSec=60

[Install]
WantedBy=multi-user.target
`
	err = os.WriteFile("/etc/systemd/system/ntpserver.service", []byte(fmt.Sprintf(service, bin)), 0644)
	if err != nil {
		log.BKEFormat(log.ERROR, fmt.Sprintf("Failed to write systemd service file: %v", err))
		return
	}
	// Enable the ntp server
	err = global.Command.ExecuteCommand("sh", "-c", "sudo systemctl enable ntpserver.service")
	if err != nil {
		log.BKEFormat(log.ERROR, fmt.Sprintf("Failed to enable ntp server: %v", err))
		return
	}
	// Reload the ntp server
	err = global.Command.ExecuteCommand("sh", "-c", "sudo systemctl daemon-reload")
	if err != nil {
		log.BKEFormat(log.ERROR, fmt.Sprintf("Failed to daemon-reload ntp server: %v", err))
		return
	}
	// Start the ntp server
	err = global.Command.ExecuteCommand("sh", "-c", "sudo systemctl start ntpserver.service")
	if err != nil {
		log.BKEFormat(log.ERROR, fmt.Sprintf("Failed to start ntp server: %v", err))
		return
	}
	log.BKEFormat(log.INFO, "Ntpserver is hosted on systemd")
}

func SystemdDaemonNTPServer() {
	ntp.Serve(utils.DefaultNTPServerPort)
}
